package com.link.base.tencent.corpwx.media.util;

import com.alibaba.fastjson.JSONObject;
import com.link.base.tencent.corpwx.media.model.CorpWxMedia;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.cllog.LCLogger;
import com.link.core.util.StringUtils;
import com.link.base.core.basic.util.YmlConstants;
import org.apache.commons.beanutils.BeanUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * 企业微信素材相关接口
 *
 * @author 李宗庭
 * @date 2019/1/25
 */
public class MediaUtil {
    /**获取临时素材接口*/
    private static final String GET_TEMP_MEDIA_API = "https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID";
    /**上传临时素材接口*/
    private static final String UPLOAD_TEMP_MEDIA_API = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";

    /**
     * 从企业微信服务器下载临时素材
     *
     * @author 李宗庭
     * @param accessToken
     * @param mediaId     素材在服务器端的Id
     * @param module      素材关联的模块
     * @return JSONObject
     * @date 2019/1/25
     */
    public static CorpWxMedia downloadMedia(String accessToken, String mediaId, String module) throws Exception {
        if (StringUtils.isBlank(accessToken)) {
            throw new BasicServiceException("accessToken不能为空！");
        }
        String requestUrl = GET_TEMP_MEDIA_API.replace("ACCESS_TOKEN", accessToken).replace("MEDIA_ID", mediaId);
        URL url = new URL(requestUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoInput(true);
        conn.setRequestMethod("GET");
        // 根据类型获取扩展名
        String fileExt = getFileExt(conn.getHeaderField("Content-Type"));
        String fileLength = conn.getHeaderField("Content-Length");
        //存放附件的根路径
        String basePath = YmlConstants.getPortalShareFileDir();
        //附件存放的绝对路径
        String pathFolder = basePath + "/" + module + "/";
        // 将mediaId作为文件名
        String path = pathFolder + mediaId + fileExt;
        //附件存放的相对路径
        String relativePath = module + "/" + mediaId + fileExt;
        LCLogger.info().withMessageKey("downloadMedia").withMessage("素材保存路径" + path).flush();
        CorpWxMedia result = new CorpWxMedia();
        result.setMediaPath(relativePath);
        result.setMediaSize(fileLength);
        result.setMediaName(mediaId + fileExt);
        result.setModuleType(module);
        result.setMediaType(conn.getHeaderField("Content-Type"));
        try {
            File filFolder = new File(pathFolder);
            if (!filFolder.exists()) {
                boolean createSuccessFlag = filFolder.mkdirs();
                if (createSuccessFlag) {
                    LCLogger.info().withMessageKey("downloadMedia")
                            .withMessage("Create folder【" + pathFolder + "】 Success").flush();
                } else {
                    LCLogger.error().withMessageKey("downloadMedia")
                            .withMessage("Create folder 【" + pathFolder + "】 Failed");
                }
            }
            try (BufferedInputStream buffer = new BufferedInputStream(conn.getInputStream())) {
                try (FileOutputStream fileOut = new FileOutputStream(new File(path))) {
                    byte[] bytes = new byte[8096];
                    int size = 0;
                    while ((size = buffer.read(bytes)) != -1) {
                        fileOut.write(bytes, 0, size);
                    }
                    fileOut.close();
                }
                buffer.close();
            }
            conn.disconnect();
            LCLogger.info().withMessageKey("downloadMedia").withMessage("下载企业微信素材成功").flush();
        } catch (Exception e) {
            LCLogger.error().withMessageKey("downloadMedia").withMessage("下载企业微信素材失败" + e);
        }
        return result;
    }

    /**
     * 上传临时素材到企业微信服务器
     *
     * @author 谢育强
     * @param accessToken 调用接口凭证
     * @param type        媒体文件类型，分别有图片（image）、语音（voice）、视频（video），普通文件（file）
     * @param file        要上传的素材文件
     * @return JSONObject
     * @date 2019/03/04
     */
    public static CorpWxMedia uploadMedia(String accessToken, String type, File file) throws Exception {
        if (StringUtils.isBlank(accessToken)) {
            throw new BasicServiceException("accessToken不能为空！");
        }
        if (!file.exists()) {
            throw new BasicServiceException("素材文件不存在！");
        }
        // 返回结果
        CorpWxMedia result = new CorpWxMedia();
        // 企业微信上传临时素材接口
        String requestUrl = UPLOAD_TEMP_MEDIA_API.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type);
        // 建立连接
        URL url = new URL(requestUrl);
        // 打开连接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        // 设置请求方式
        conn.setRequestMethod("POST");
        // 输入输出设置
        conn.setDoInput(true);
        conn.setDoOutput(true);
        // post方式不能使用缓存
        conn.setUseCaches(false);
        // 设置请求头信息
        conn.setRequestProperty("Connection", "Keep-Alive");
        conn.setRequestProperty("Charset", "UTF-8");
        // 设置边界
        String BOUNDARY = "----------" + System.currentTimeMillis();
        conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
        // 设置正文表头信息
        StringBuffer content = new StringBuffer();
        content.append("--");
        content.append(BOUNDARY);
        content.append("\r\n");
        // 上传临时素材接口固定内容
        content.append("Content-Disposition: form-data;name=\"media\";filelength=\"" + file.length()
                + "\";filename=\"" + file.getName() + "\"\r\n");
        content.append("Content-Type:application/octet-stream\r\n\r\n");
        byte[] head = content.toString().getBytes("utf-8");
        try {
            // 获取输出流，并将表头写入输出流中
            try (OutputStream outputStream = new DataOutputStream(conn.getOutputStream())) {
                outputStream.write(head);
                // 将文件正文部分以文件流的方式写入到微信服务器中
                try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
                    int bytes;
                    byte[] bufferOut = new byte[1024];
                    while ((bytes = in.read(bufferOut)) != -1) {
                        outputStream.write(bufferOut, 0, bytes);
                    }
                    in.close();
                }
                // 将结尾部分输出到微信服务器， 定义最后数据分隔线
                byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");
                outputStream.write(foot);
                outputStream.flush();
                outputStream.close();
            }
            // 将微信服务器返回的输入流转换成字符串
            try (InputStream inputStream = conn.getInputStream();
                 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"))) {
                StringBuilder buffer = new StringBuilder();
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    buffer.append(line);
                }
                // 将返回值插入返回结果中
                JSONObject jsonObject = JSONObject.parseObject(buffer.toString());
                result.setMediaId(jsonObject.get("media_id").toString());
                // 释放资源
                bufferedReader.close();
                inputStream.close();
            }
            // 关闭连接
            conn.disconnect();
        } catch (Exception e) {
            LCLogger.error().withMessageKey("uploadMedia").withMessage("上传企业微信素材失败: " + e);
        }
        return result;
    }

    /**
     * 根据内容类型判断文件扩展名
     *
     * @author 李宗庭
     * @param contentType
     * @return string
     * @date 2019/1/25
     */
    public static String getFileExt(String contentType) {
        String fileExt ;
        switch (contentType) {
            case "image/jpeg":
                fileExt = ".jpg";
                break;
            case "audio/mpeg":
                fileExt = ".mp3";
                break;
            case "audio/amr":
                fileExt = ".amr";
                break;
            case "video/mp4":
                fileExt = ".mp4";
                break;
            case "video/mpeg4":
                fileExt = ".mp4";
                break;
            default:
                fileExt = ".jpg";
        }
        return fileExt;
    }

    /**
     * 根据传入的list，生成csv文件
     *
     * @author 李宗庭
     * @param  exportData 需导入List
     * @param  map 表头 LinkedHashMap类型
     * @param  outPutPath 文件路径
     * @return  File
     * @date 2019/3/7
     */
    public static File createCSVFile(List exportData, LinkedHashMap map, String outPutPath) {
        File csvFile = null;
        BufferedWriter csvFileOutputStream = null;
        try {
            File file = new File(outPutPath);
            if (!file.exists()) {
                file.mkdir();
            }
            //定义文件名格式并创建
            csvFile = File.createTempFile("Link", ".csv", new File(outPutPath));
            LCLogger.info().withMessageKey("createCSVFile").withMessage("生成的csv文件：" + csvFile).flush();
            // UTF-8使正确读取分隔符","
            FileOutputStream fos = new FileOutputStream(csvFile);
            // 写入bom头
            byte[] uft8bom = {(byte)0xef,(byte)0xbb,(byte)0xbf};
            fos.write(uft8bom);
            csvFileOutputStream = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"), 1024);
            // 写入文件头部
            for (Iterator propertyIterator = map.entrySet().iterator(); propertyIterator.hasNext();) {
                java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator.next();
                csvFileOutputStream
                        .write((String) propertyEntry.getValue() != null ? (String) propertyEntry.getValue() : "");
                if (propertyIterator.hasNext()) {
                    csvFileOutputStream.write(",");
                }
            }
            csvFileOutputStream.newLine();
            // 写入文件内容
            for (Iterator iterator = exportData.iterator(); iterator.hasNext();) {
                Object row = iterator.next();
                for (Iterator propertyIterator = map.entrySet().iterator(); propertyIterator.hasNext();) {
                    java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator.next();
                    String value = BeanUtils.getProperty(row, (String) propertyEntry.getKey());
                    value = value == null ? "" : value;
                    csvFileOutputStream.write(value);
                    if (propertyIterator.hasNext()) {
                        csvFileOutputStream.write(",");
                    }
                }
                if (iterator.hasNext()) {
                    csvFileOutputStream.newLine();
                }
            }
            csvFileOutputStream.flush();
        } catch (Exception e) {
            LCLogger.error().withMessageKey("createCSVFile").withMessage("生成CSV文件失败: " + e);
        } finally {
            try {
                csvFileOutputStream.close();
            } catch (IOException e) {
                LCLogger.error().withMessageKey("createCSVFile").withMessage("关闭文件流失败: " + e);
            }
        }
        return csvFile;
    }
}
